package morning.cat.study.kryo;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.pool.KryoPool;
import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 其使用了字节码生成机制（底层依赖了 ASM 库）
 */
public class KryoSerializableTest {

    @Test
    public void test() throws IOException {
        // 序列化
        Kryo kryo = new Kryo();
        Output output = new Output(new FileOutputStream("kryo.bin"));
        kryo.writeObject(output, getUser());
        output.close();
    }

    @Test
    public void test2() throws IOException {
        // 反序列化
        Kryo kryo = new Kryo();
        Input input = new Input(new FileInputStream("kryo.bin"));
        User2 user = kryo.readObject(input, User2.class);
        System.out.println(user);
    }

    private User2 getUser() {
        User2 user = new User2();
        user.setId(System.currentTimeMillis());
        user.setName("Kryo_" + System.currentTimeMillis());
        user.setDate(Calendar.getInstance().getTime());
        user.setStr("transient 关键字标记 不参与序列化");
        System.out.println(user);
        return user;
    }

    private static final ThreadLocal<Kryo> kryos =
            new ThreadLocal<Kryo>() {
                @Override
                protected Kryo initialValue() {
                    Kryo kryo = new Kryo();
                    return kryo;
                }
            };

    @Test
    public void test3() throws FileNotFoundException {

        String fileName = "kryo_test3_3.bin";

        // ThreadLocal 方式
        Kryo kryo = kryos.get();
        kryo.setRegistrationRequired(false);//关闭注册行为
        kryo.setReferences(true);//支持循环引用
        Output output = new Output(new FileOutputStream(fileName));
        kryo.writeClassAndObject(output, getUser());
        output.close();

        Input input = new Input(new FileInputStream(fileName));
        Object object = kryo.readClassAndObject(input);
        if (object instanceof User2) {
            User2 user = (User2) object;
            System.out.println(user);
        }
    }


    @Test
    public void test4() {
        // 池技术
        KryoPool kryoPool = new KryoPool.Builder(() -> new Kryo()).queue(new ArrayBlockingQueue<>(20)).build();
        Kryo kryo = kryoPool.borrow();


        kryoPool.release(kryo);
    }

    @Test
    public void test5() {
        int c = 5;
        while (c-- > 0) {
            int max = (int) (Math.random() * 4);
            System.out.print(max + " ");
        }


    }


}
